package com.lzw.breezeNovel.webApp.service.impl.novel;


import com.lzw.breezeNovel.common.login.LoginUser;
import com.lzw.breezeNovel.common.login.LoginUserHolder;

import com.lzw.breezeNovel.model.entity.pojo.novel.Book;
import com.lzw.breezeNovel.model.entity.pojo.novel.Rating;
import com.lzw.breezeNovel.model.entity.pojo.user.UserInfo;
import com.lzw.breezeNovel.webApp.mapper.novel.BookMapper;
import com.lzw.breezeNovel.webApp.mapper.novel.RatingMapper;
import com.lzw.breezeNovel.webApp.mapper.user.UserInfoMapper;
import com.lzw.breezeNovel.webApp.service.novel.RatingService;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Date;
import java.util.concurrent.*;

/**
 * @author 清风明月
 * @Package com.lzw.breezeNovel.webApp.service.novel.impl
 * @date 2025/3/2
 * @description 评分的服务实现类
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class RatingServiceImpl implements RatingService {

    /**
     * 注入mapper
     */
    @Autowired
    private RatingMapper ratingMapper;

    /**
     * 注入用户mapper
     */
    @Autowired
    private UserInfoMapper userInfoMapper;

    /**
     * 注入小说mapper
     */
    @Autowired
    private BookMapper bookMapper;

    /**
     * 线程池
     */
    @Autowired
    private ThreadPoolExecutor executor;

    /**
     * 进行评分
     * @param bookId
     * @param score
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rateBook(Long bookId, @NotNull @Min(0) @Max(5) BigDecimal score) {
        // 获取当前用户
        LoginUser loginUser = LoginUserHolder.getLoginUser();
        // 获取当前用户的手机号
        String phone = loginUser.getPhone();

        //异步的凡是更新评分
        CompletableFuture<Void> updateBookFuture = CompletableFuture.runAsync(() -> {
            updateBookRating(bookId, score);
        }, executor);

        //异步的方式获取评分
        CompletableFuture<Void> insertRatingFuture = CompletableFuture.runAsync(() -> {
            insertUserRating(phone, bookId, score);
        }, executor);

        // 确保两个任务都完成，并处理异常
        CompletableFuture.allOf(updateBookFuture, insertRatingFuture).exceptionally(ex -> {
            log.error("评分任务执行失败", ex.getCause());
            throw new CompletionException(ex.getCause());
        }).join();
    }

    /**
     * 更新小说评分
     * @param bookId
     * @param score
     */
    @Transactional(rollbackFor = Exception.class)
    private void updateBookRating(Long bookId, BigDecimal score) {
        // 根据 bookId 查询小说
        Book book = bookMapper.selectById(Long.valueOf(bookId));
        if (book == null) {
            throw new IllegalArgumentException("小说不存在");
        }

        // 获取当前小说的总评分和评分人数
        BigDecimal totalScore = book.getTotalScore();
        Long ratingCount = book.getRatingCount();

        // 计算新的总评分
        BigDecimal newTotalScore = totalScore.multiply(new BigDecimal(ratingCount))
                .add(score)
                .divide(new BigDecimal(ratingCount + 1), 2, BigDecimal.ROUND_HALF_UP);
        book.setTotalScore(newTotalScore);
        book.setRatingCount(ratingCount + 1);
        book.setUpdateTime(new Date());
        // 更新小说
        bookMapper.updateById(book);
    }

    /**
     * 插入用户评分记录
     * @param phone
     * @param bookId
     * @param score
     */
    @Transactional(rollbackFor = Exception.class)
    private void insertUserRating(String phone, Long bookId, BigDecimal score) {
        // 根据手机号查询用户
        UserInfo userInfo = userInfoMapper.selectByPhone(phone);
        if (userInfo == null) {
            throw new IllegalArgumentException("用户不存在");
        }
        // 创建评分对象
        Rating rating = new Rating();
        rating.setRatingTime(new Date());
        rating.setBookId(bookId);
        rating.setUserId(userInfo.getUserId());
        rating.setScore(score);
        // 插入评分记录
        ratingMapper.insert(rating);
    }


}
